import 'package:base_plugin/base_plugin.dart';
import 'package:finance_app/generated/l10n.dart';
import 'package:finance_app/src/common/app_colors.dart';
import 'package:finance_app/src/third_part/speech_to_text.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:google_speech/generated/google/cloud/speech/v1/cloud_speech.pb.dart';

class SpeechBottomWidget extends StatefulWidget {
  final TextEditingController controller;
  final VoidCallback onSend;

  const SpeechBottomWidget({Key key, this.controller, this.onSend})
      : super(key: key);

  @override
  _SpeechBottomWidgetState createState() => _SpeechBottomWidgetState();
}

class _SpeechBottomWidgetState extends State<SpeechBottomWidget> {
  bool _isListening = false;

  String localeId;

  bool hasText;

  bool hasEnd = false;

  String lastText;
  var listener;

  @override
  void initState() {
    super.initState();
    activateSpeechRecognizer();
    if (widget.controller != null) {
      hasText = widget.controller.text.length > 0;
      listener = () {
        if (hasText == true && widget.controller.text.length == 0) {
          setState(() {
            hasText = false;
          });
        } else if (hasText == false && widget.controller.text.length > 0) {
          setState(() {
            hasText = true;
          });
        }
      };

      widget.controller.addListener(listener);
    }
  }

  @override
  void dispose() {
    super.dispose();
    widget.controller.removeListener(listener);
    SpeechToText().stop();
  }

  void activateSpeechRecognizer() async {
    print('_MyAppState.activateSpeechRecognizer... ');
    await SpeechToText().initEngine();
  }

  void start() {
    if (SpeechToText().canUse == true) {
      //可用
      lastText = widget.controller.text;
      setState(() {
        hasEnd = false;
        _isListening = true;
      });
      SpeechToText().onListener(_onResultListener);
    } else {
      BaseConfig.dialogBase.showToast(
          context: context, content: S.current.speech_to_text_unable);
    }
  }

  void cancel() {
    setState(() {
      hasEnd = false;
      _isListening = false;
    });
    SpeechToText().stop();
  }

  void stop() async {
    setState(() {
      hasEnd = true;
      _isListening = false;
    });
    SpeechToText().stop();
  }

  @override
  Widget build(BuildContext context) {
    return ColoredBox(
      color: aceWhiteGreyColor,
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.center,
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Text(
            _isListening
                ? S.current.release_when_done
                : hasText
                    ? S.current.hold_to_continue_recording
                    : S.current.hold_to_start_speech_recognition,
            style: TextStyle(
              color: aceDarkGrayColor,
              fontSize: getSp(16),
              fontWeight: FontWeight.w400,
              height: 22 / 16,
            ),
          ),
          SizedBox(
            height: getDp(30),
          ),
          Row(
            mainAxisAlignment: MainAxisAlignment.center,
            crossAxisAlignment: CrossAxisAlignment.center,
            children: [
              if (hasEnd && hasText)
                PressedOpacityButton(
                  onPressed: () {
                    widget.controller.clear();
                  },
                  child: Text(
                    S.current.clear,
                    style: TextStyle(
                      color: aceBlueColor,
                      fontSize: getSp(16),
                      fontWeight: FontWeight.w700,
                      height: 22 / 16,
                    ),
                  ),
                ),
              SizedBox(
                width: getDp(50),
              ),
              _buildButton(
                icon: _isListening
                    ? Icon(
                        Icons.circle,
                        color: Colors.white,
                        size: getDp(30),
                      )
                    : Icon(
                        Icons.mic_rounded,
                        color: Colors.white,
                        size: getDp(45),
                      ),
                color: _isListening ? aceRedColor : aceBlueColor,
              ),
              SizedBox(
                width: getDp(50),
              ),
              if (hasEnd && hasText)
                PressedOpacityButton(
                  onPressed: () {
                    widget.onSend?.call();
                  },
                  child: Text(
                    S.current.send,
                    style: TextStyle(
                      color: aceBlueColor,
                      fontSize: getSp(16),
                      fontWeight: FontWeight.w700,
                      height: 22 / 16,
                    ),
                  ),
                ),
            ],
          ),
        ],
      ),
    );
  }

  Widget _buildButton({Icon icon, Color color}) => GestureDetector(
        key: ValueKey('onTap'),
        onTapDown: _onTapDown,
        onTapUp: _onTapUp,
        onTapCancel: _onTapCancel,
        child: Container(
            width: getDp(80),
            height: getDp(80),
            decoration:
                BoxDecoration(color: color, shape: BoxShape.circle, boxShadow: [
              BoxShadow(
                color: Colors.black.withOpacity(0.25),
                offset: Offset(0, 5),
                blurRadius: getDp(10),
              )
            ]),
            alignment: Alignment.center,
            child: icon),
      );

  void _onTapDown(TapDownDetails details) {
    HapticFeedback.lightImpact();
    start();
  }

  void _onTapUp(TapUpDetails details) {
    HapticFeedback.mediumImpact();
    stop();
  }

  void _onTapCancel() {
    HapticFeedback.mediumImpact();
    stop();
  }

  void _onResultListener(StreamingRecognizeResponse data) {
    final currentText =
        data.results.map((e) => e.alternatives.first.transcript).join('');
    String _text;
    if (data.results.first.isFinal) {
      lastText += currentText;
      _text = '${lastText ?? ''}';
    } else {
      _text = '${lastText ?? ''}$currentText';
    }
    widget.controller.value = TextEditingValue(
      text: _text,
      selection: TextSelection.collapsed(offset: _text.length),
    );
  }
}
